# koroFileHeader at Yungoal acer
# Create: 2022-10-08 14:49:44
# LastEdit: 2023-10-20 10:25:49
"""设置终端配色方案,参考:
添加彩色格式: django.utils.termcolors.py
生成Style类自动添加彩色格式: django.core.management.color.py
"""
__author__ = '749B'

import os
import sys

try:
    import colorama
    colorama.init()
except (ImportError, OSError):
    HAS_COLORAMA = False
else:
    HAS_COLORAMA = True


class Style:

    def __init__(self) -> None:
        self.colorful = self.supports_color()

    @staticmethod
    def supports_color():
        """
        Return True if the running system's terminal supports color,
        and False otherwise.
        """
        def vt_codes_enabled_in_windows_registry():
            """
            Check the Windows Registry to see if VT code handling has been enabled
            by default, see https://superuser.com/a/1300251/447564.
            """
            try:
                # winreg is only available on Windows.
                import winreg
            except ImportError:
                return False
            else:
                reg_key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, 'Console')
                try:
                    reg_key_value, _ = winreg.QueryValueEx(reg_key, 'VirtualTerminalLevel')
                except FileNotFoundError:
                    return False
                else:
                    return reg_key_value == 1

        # isatty is not always implemented, #6223.
        is_a_tty = hasattr(sys.stdout, 'isatty') and sys.stdout.isatty()

        return is_a_tty and (
            sys.platform != 'win32' or
            HAS_COLORAMA or
            'ANSICON' in os.environ or
            # Windows Terminal supports VT codes.
            'WT_SESSION' in os.environ or
            # Microsoft Visual Studio Code's built-in terminal supports colors.
            os.environ.get('TERM_PROGRAM') == 'vscode' or
            vt_codes_enabled_in_windows_registry()
        )

    @staticmethod
    def colorize(text='', opts=(), **kwargs):
        """
        Return your text, enclosed in ANSI graphics codes.

        Depends on the keyword arguments 'fg' and 'bg', and the contents of
        the opts tuple/list.

        Return the RESET code if no parameters are given.

        Valid colors:
            'black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white'

        Valid options:
            'bold'
            'underscore'
            'blink'
            'reverse'
            'conceal'
            'noreset' - string will not be auto-terminated with the RESET code

        Examples:
            colorize('hello', fg='red', bg='blue', opts=('blink',))
            colorize()
            colorize('goodbye', opts=('underscore',))
            print(colorize('first line', fg='red', opts=('noreset',)))
            print('this should be red too')
            print(colorize('and so should this'))
            print('this should not be red')
        """
        color_names = ('black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white')
        foreground = {color_names[x]: '3%s' % x for x in range(8)}
        background = {color_names[x]: '4%s' % x for x in range(8)}
        RESET = '0'
        opt_dict = {'bold': '1', 'underscore': '4', 'blink': '5', 'reverse': '7', 'conceal': '8'}

        code_list = []
        if text == '' and len(opts) == 1 and opts[0] == 'reset':
            return '\x1b[%sm' % RESET
        for k, v in kwargs.items():
            if k == 'fg':
                code_list.append(foreground[v])
            elif k == 'bg':
                code_list.append(background[v])
        for o in opts:
            if o in opt_dict:
                code_list.append(opt_dict[o])
        if 'noreset' not in opts:
            text = '%s\x1b[%sm' % (text or '', RESET)
        # return '%s%s' % (('\x1b[%sm' % ';'.join(code_list)), text or '')
        # django里的return有BUG,用下面的return修复
        return '%s%s' % (('\x1b[%sm' % ';'.join(code_list)) if code_list else '', text or '')

    def RESET(self, text: str) -> str:
        return self.colorize(text) if self.colorful else text

    def CRITICAL(self, text: str, noreset: bool = False) -> str:
        return self.colorize(text, fg='red', opts=('bold',) if not noreset else ('bold', 'noreset')) if self.colorful else text

    def ERROR(self, text: str, noreset: bool = False) -> str:
        return self.colorize(text, fg='red', opts=() if not noreset else ('noreset',)) if self.colorful else text

    def WARNING(self, text: str, noreset: bool = False) -> str:
        return self.colorize(text, fg='yellow', opts=() if not noreset else ('noreset',)) if self.colorful else text

    def INFO(self, text: str, noreset: bool = False) -> str:
        return self.colorize(text, fg='blue', opts=('bold',) if not noreset else ('bold', 'noreset',)) if self.colorful else text

    def DEBUG(self, text: str, noreset: bool = False) -> str:
        return self.colorize(text, fg='cyan', opts=('underscore',) if not noreset else ('underscore', 'noreset')) if self.colorful else text

    def NOTSET(self, text: str, noreset: bool = False) -> str:
        return self.colorize(text, opts=('cyan',) if not noreset else ('bold', 'noreset')) if self.colorful else text

    def SUCCESS(self, text: str, noreset: bool = False) -> str:
        return self.colorize(text, fg='green', opts=('bold',) if not noreset else ('bold', 'noreset')) if self.colorful else text


if __name__ == '__main__':
    from pathlib import Path
    style = Style()
    message = 'Message from {} in {} style'
    print(style.CRITICAL(message.format('.'.join(Path(__file__).parts[-2:]), 'CRITICAL')))
    print(style.ERROR(message.format('.'.join(Path(__file__).parts[-2:]), 'ERROR')))
    print(style.WARNING(message.format('.'.join(Path(__file__).parts[-2:]), 'WARNING')))
    print(style.INFO(message.format('.'.join(Path(__file__).parts[-2:]), 'INFO')))
    print(style.DEBUG(message.format('.'.join(Path(__file__).parts[-2:]), 'DEBUG')))
    print(style.NOTSET(message.format('.'.join(Path(__file__).parts[-2:]), 'NOTSET')))
    print(style.SUCCESS(message.format('.'.join(Path(__file__).parts[-2:]), 'SUCCESS')))

    print(style.CRITICAL('first line', noreset=True))
    print('this should be red too')
    print(style.RESET('and so should this'))
    print('this should not be red')
